package com.alipay.service.listener;


import com.alipay.exception.CustomException;
import com.alipay.exception.MqConsumeException;
import com.alipay.exception.RiskAccountException;
import com.alipay.model.dto.TransDto;
import com.alipay.model.enums.QueueEnum;
import com.alipay.service.AccountService;
import com.alipay.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author Jun
 * 监听A扣款成功后，增加B的余额
 */
@Slf4j
@Service
public class TansTaskDecreaseMessageListener {

    @Resource
    private AccountService accountService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Transactional(rollbackFor = Exception.class)
    @RabbitListener(queues = "${rabbitmq.increase.queue}")
    protected void onMessage(String message){
        TransDto transDto = JsonUtil.fromJson(message, TransDto.class);
        try {
            // 参数有效性校验, 省略
            if (transDto == null) {
                return;
            }
            // 增加入款账户余额
            boolean flag = accountService.increase(transDto);

            // 非业务的异常进行重试
            if (!flag) {
                log.error("increase failed, the transId is {}", transDto.getTransId());
                throw new CustomException("增加余额失败，transId：" + transDto.getTransId());
            } else {
                // 发送成功的状态，让A系统改成最终态,非最终状态的有A在经验值时间进行补偿
                rabbitTemplate.convertAndSend(
                        QueueEnum.SUCCESS_QUEUE.getName(),
                        JsonUtil.toJson(transDto));
            }
        } catch (RiskAccountException e) {
            log.error("increase failed , the transId is {}", transDto.getTransId());
            // 业务上的异常，通知A系统进行回滚，这里需要用MQ的ack确认机制，保证消息发送成功
            rabbitTemplate.convertAndSend(
                    QueueEnum.ROLLBACK_QUEUE.getName(),
                    JsonUtil.toJson(transDto));
        } catch (Exception e) {
            log.error("message consumer failed , the transId is {}", transDto.getTransId(), e);
            throw new MqConsumeException("增加余额失败，e：", e);
        }

        // TODO 手动提交rabbit mq的ack确认
    }


}
